package com.chen.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.generator.config.IFileCreate;
import com.chen.dto.CreateOrderDto;
import com.chen.entity.*;
import com.chen.mapper.*;
import com.chen.service.CartItemService;
import com.chen.service.OrderItemService;
import com.chen.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.service.TokenService;
import com.chen.utils.RedisWorker;
import com.chen.utils.UserThreadLocal;
import com.chen.vo.CartProduct;
import com.chen.vo.OrderVo;
import com.chen.vo.Result;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.chen.constant.RedisConstants.MALL_ORDER_TIEM;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author cws
 * @since 2024-11-27
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private CartItemService cartItemService;

    @Autowired
    private RedisWorker redisWorker;

    @Resource
    private CouponMapper couponMapper;

    @Resource
    private MemberReceiveAddressMapper memberReceiveAddressMapper;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private CouponHistoryMapper couponHistoryMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private OrderSettingMapper orderSettingMapper;

    @Resource
    UserMapper userMapper;

    @Autowired
    private TokenService tokenService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result createOrder(CreateOrderDto createOrderDto, String token) {
        if (Collections.isEmpty(createOrderDto.getProductIds()) || createOrderDto.getProductIds().size() == 0) {
            throw new RuntimeException("商品id不能为空~");
        }
        if (createOrderDto.getAddressId() == null) {
            throw new RuntimeException("请选择收货地址~");
        }
//        获取默认地址
        MemberReceiveAddress address = memberReceiveAddressMapper.selectById(createOrderDto.getAddressId());
        List<Long> productIds = createOrderDto.getProductIds();
        List<CartProduct> cartProduct = cartItemService.getCartProduct(productIds);
        if (cartProduct.size() == 0) {
            throw new RuntimeException("商品不存在~");
        }
//        总金额
        User user = UserThreadLocal.get();
//        TODO 创建订单
        Order order = generateOrder(user, createOrderDto, cartProduct, address);
        orderMapper.insert(order);
//       创建子集mall_cart_item
        List<OrderItem> orderItemList = generateOrderItem(user, cartProduct, order);
//        加入数据库
        orderItemService.saveBatch(orderItemList);
        //todo 清除购物车
        List<Long> cartIds = cartProduct.stream().map(CartProduct::getCartId).collect(Collectors.toList());
        cartItemService.deleteCartItemByIds(cartIds);
        //      TODO 存入redis 后监听redis是否超时
        List<OrderSetting> orderSettings = orderSettingMapper.selectList(null);
        OrderSetting orderSetting = orderSettings.get(0);
        String key = MALL_ORDER_TIEM + order.getOrderSn();
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(order),
                orderSetting.getNormalOrderOvertime(), TimeUnit.MINUTES);
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderSn", order.getOrderSn());
        map.put("id", order.getId());
//       刷新缓存
        tokenService.refreshToken(token);
        return Result.success(map);
    }

    /**
     * 获取订单支付信息
     *
     * @param orderSn
     * @return
     */
    @Override
    public Result getOrderPayList(String orderSn) {
        User user = UserThreadLocal.get();
        LambdaQueryWrapper<OrderItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderItem::getOrderSn, orderSn);
        List<OrderItem> list = orderItemService.list(wrapper);
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn, orderSn));
        String key = MALL_ORDER_TIEM + orderSn;
        Long expire = stringRedisTemplate.getExpire(key);
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderItemList", list);
        map.put("expire", expire);
        map.put("payPrice", order.getPayAmount());
        map.put("UserBalance", user.getBalance());
        return Result.success(map);
    }

    /**
     * 余额支付
     *
     * @param orderSn
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result balancePay(String orderSn, String token) {
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn, orderSn));
        //        扣减余额
        Long userId = order.getUserId();
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在~");
        }
        if (user.getBalance().compareTo(order.getPayAmount()) == -1) {
            throw new RuntimeException("余额不足~");
        }
        user.setBalance(user.getBalance().subtract(order.getPayAmount()));
        userMapper.updateById(user);
        order.setPayType(2);
        order.setPaymentTime(LocalDateTime.now());
        order.setStatus(1);
        orderMapper.updateById(order);
        tokenService.refreshToken(token);//更新缓存
//        清除订单缓存
        stringRedisTemplate.delete(MALL_ORDER_TIEM + order.getOrderSn());
        return Result.success();
    }

    /**
     * 处理订单超时
     *
     * @param orderSn
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void UpdateTimeOutOrder(String orderSn) {
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn, orderSn));
        if (order==null)return;
        order.setPayType(0);
        order.setStatus(4);
        int i1 = orderMapper.updateById(order);
        log.info("订单状态修改：{}", i1);

//        1.返回优惠卷
        if (order.getCouponId() != null) {
            CouponHistory couponHistory = couponHistoryMapper.
                    selectOne(new LambdaQueryWrapper<CouponHistory>()
                            .eq(CouponHistory::getId, order.getCouponId()));
            if (couponHistory != null){
                couponHistory.setUseStatus(0);
                int i = couponHistoryMapper.updateById(couponHistory);
                log.info("返还优惠卷：{}",i);
            }
        }
//    2.返还积分
        if(order.getUseIntegration() != null&&order.getUseIntegration()>0){
         int i =  userMapper.updateIntegration(order.getUserId(), order.getUseIntegration());
         log.info("返还积分：{}",i);
        }

    }

    @Override
    public Result OrderAllList(Integer status) {
        User user = UserThreadLocal.get();
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getUserId, user.getId());
        wrapper.eq(Order::getStatus, status);
        wrapper.eq(Order::getDeleteStatus, 0);
        List<Order> orders = orderMapper.selectList(wrapper);
        List<OrderVo> orderVoList = new ArrayList<>();
        for (Order order : orders) {
//            查询字商品
            OrderVo orderVo = new OrderVo();
            orderVo.setOrder(order);
            LambdaQueryWrapper<OrderItem> orderItemWrapper = new LambdaQueryWrapper<>();
            orderItemWrapper.eq(OrderItem::getOrderId, order.getId());
            List<OrderItem> list = orderItemService.list(orderItemWrapper);
            orderVo.setOrderItemList(list);
            orderVoList.add(orderVo);
            if (status.equals(0)){
                Long expire = stringRedisTemplate.getExpire(MALL_ORDER_TIEM + order.getOrderSn());
                orderVo.setTimeout(expire);
            }
        }
        return Result.success(orderVoList);
    }

    @Override
    public Result updateStatus(Long id, Integer status) {
        LambdaUpdateWrapper<Order> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Order::getId, id);
        wrapper.set(Order::getStatus, status);
        orderMapper.update(null, wrapper);
        return Result.success();
    }

    //    生成订单子集
    private List<OrderItem> generateOrderItem(User user, List<CartProduct> cartProduct, Order order) {
        List<OrderItem> list = new ArrayList<>();
        try {
            for (CartProduct cartProductNext : cartProduct) {
                OrderItem orderItem = new OrderItem();
                Product product = productMapper.selectById(cartProductNext.getProductId());
                orderItem.setOrderId(order.getId());
                orderItem.setOrderSn(order.getOrderSn());
                orderItem.setProductId(product.getId());
                orderItem.setProductPic(cartProductNext.getDefaultPic());
                orderItem.setProductName(cartProductNext.getProductName());
                orderItem.setProductBrand(cartProductNext.getBrandName());
                orderItem.setProductSn("");
                orderItem.setProductPrice(cartProductNext.getTotalPrice());
                orderItem.setProductQuantity(cartProductNext.getQuantity());
                orderItem.setProductSkuId(cartProductNext.getProductSkuId());
                orderItem.setProductSkuCode("");
                orderItem.setProductRegionId(Long.valueOf(product.getRegionId()));
                orderItem.setPromotionName(cartProductNext.getPromotionName());
                orderItem.setPromotionAmount(cartProductNext.getPromotionAmount());// 满减优惠
                orderItem.setCouponAmount(order.getCouponAmount());// 优惠券优惠
                orderItem.setIntegrationAmount(order.getIntegrationAmount());
                orderItem.setRealAmount(cartProductNext.getTotalPrice().subtract(cartProductNext.getPromotionAmount()));
                orderItem.setGiftIntegration(0);
                orderItem.setGiftGrowth(0);
                orderItem.setProductAttr(cartProductNext.getProductAttr());
                list.add(orderItem);
            }
        } catch (Exception e) {
            log.error("生成子订单失败~", e);
            throw new RuntimeException("生成子订单失败~");
        }
        return list;
    }


    //    创建订单
    private Order generateOrder(User user, CreateOrderDto createOrderDto,
                                List<CartProduct> cartProduct,
                                MemberReceiveAddress address
    ) {
        Order order = new Order();
        try {
            //        获取优惠卷
            Coupon coupon = null;
            BigDecimal ProductAllPrice = getProductAllPrice(cartProduct);
            Long userId = user.getId();
            order.setUserId(userId);
            if (createOrderDto.getUseCoupon()) {
                coupon = couponMapper.selectById(createOrderDto.getCouponId());
                order.setCouponAmount(coupon.getAmount());
                order.setCouponId(createOrderDto.getCouponId());
//            TODO 改变我的对应优惠卷状态
                LambdaUpdateWrapper<CouponHistory> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(CouponHistory::getCouponId, coupon.getId());
                wrapper.set(CouponHistory::getUseStatus, 1);
                couponHistoryMapper.update(null, wrapper);
            }
            long orderNo = redisWorker.nextId("order");
            log.info("生成的订单号：{}", orderNo);
            order.setOrderSn("NO" + String.valueOf(orderNo));
            order.setCreateTime(LocalDateTime.now());// 创建时间
            order.setMemberUsername(UserThreadLocal.get().getUsername());// 用户名
            order.setTotalAmount(ProductAllPrice);// 订单总额
            log.info("订单总金额：{}", orderNo);
//       获取支付金额
            Integer integration = null;
            if (createOrderDto.getUseIntegration()) {
                order.setUseIntegration(user.getIntegration());
                integration = user.getIntegration() / 100;
                log.info("使用积分转换为：{}  元", integration);
                //        积分抵扣金额
                order.setIntegrationAmount(BigDecimal.valueOf(integration));
//                TODO 更新User积分
                user.setIntegration(0);
                userMapper.updateById(user);
            } else {
                order.setIntegrationAmount(BigDecimal.ZERO);
            }
            BigDecimal payAmount = getPayAmount(cartProduct, coupon, integration);
            log.info("订单支付金额：{}", orderNo);
            order.setPayAmount(payAmount);

//        促销优惠总价格
            BigDecimal promotionAmount = getPromotionAmount(cartProduct);
            order.setPromotionAmount(promotionAmount);
//        运费为 o
            order.setFreightAmount(BigDecimal.ZERO);
            order.setDiscountAmount(BigDecimal.ZERO);
            order.setStatus(0);
//活动信息
            String promotionInfo = getPromotionInfo(cartProduct);
            if (StringUtils.isEmpty(promotionInfo)) {
                order.setPromotionInfo("无优惠");
            } else {
                order.setPromotionInfo(promotionInfo);
            }
//        收件人姓名
            order.setReceiverName(address.getName());
            order.setReceiverPhone(address.getPhoneNumber());// 收货人电话
            order.setReceiverPostCode(address.getPostCode());// 邮政编码
            order.setReceiverProvince(address.getProvince());
            order.setReceiverCity(address.getCity());
            order.setReceiverRegion(address.getRegion());
            order.setReceiverDetailAddress(address.getDetailAddress());
            order.setAutoConfirmDay(7);// 自动确认时间（天）
            order.setConfirmStatus(0);// 确认收货状态：0->未确认；1->已确认
            order.setDeleteStatus(0);// 删除状态：0->未删除；1->已删除
//            赠送积分
            Integer integer = cartProduct.stream().map(CartProduct::getGiftPoint).reduce(Integer::sum).get();
            order.setIntegration(integer);
        } catch (Exception e) {
            log.error("创建主订单异常~~~~~");
            e.printStackTrace();
            throw new RuntimeException("创建主订单失败~");
        }
        return order;
    }


    //    计算总金额
    private BigDecimal getProductAllPrice(List<CartProduct> cartProducts) {
        if (cartProducts == null || cartProducts.isEmpty()) {
            return BigDecimal.ZERO;
        }

        BigDecimal productPrice = BigDecimal.ZERO;
        try {
            for (CartProduct cartProduct : cartProducts) {
                // 价格 * 数量
                BigDecimal multiply = cartProduct.getPrice().multiply(BigDecimal.valueOf(cartProduct.getQuantity()));
                productPrice = productPrice.add(multiply);
            }
        } catch (NullPointerException e) {
            // 处理空指针异常
            System.err.println("Error: Null value encountered in cart products.");
            e.printStackTrace();
        } catch (Exception e) {
            // 处理其他异常
            System.err.println("Error: Unexpected exception occurred.");
            e.printStackTrace();
        }

        return productPrice;
    }


    //    计算支付金额
    private BigDecimal getPayAmount(List<CartProduct> cartProducts, Coupon coupon, Integer useIntegration) {
        if (cartProducts == null || cartProducts.isEmpty()) {
            return BigDecimal.ZERO;
        }

        BigDecimal payAmount = BigDecimal.ZERO;
        for (CartProduct cartProduct : cartProducts) {
            if (cartProduct == null) {
                continue;
            }
            BigDecimal multiply = cartProduct.getTotalPrice().multiply(BigDecimal.valueOf(cartProduct.getQuantity()));
            payAmount = payAmount.add(multiply);
        }

        if (coupon != null && coupon.getAmount().compareTo(BigDecimal.ZERO) > 0) {
            try {
                payAmount = payAmount.subtract(coupon.getAmount());
            } catch (ArithmeticException e) {
                // 处理除法异常
                System.err.println("Error dividing by coupon amount: " + e.getMessage());
                return BigDecimal.ZERO;
            }
        }

        if (useIntegration != null && useIntegration > 0) {
            try {
                payAmount = payAmount.subtract(BigDecimal.valueOf(useIntegration));
            } catch (ArithmeticException e) {
                // 处理除法异常
                System.err.println("Error dividing by useIntegration: " + e.getMessage());
                return BigDecimal.ZERO;
            }
        }

        return payAmount;
    }


    //计算促销减去金额
    private BigDecimal getPromotionAmount(List<CartProduct> cartProducts) {
        BigDecimal promotionAmount = BigDecimal.ZERO;
        for (CartProduct cartProduct : cartProducts) {
            promotionAmount = promotionAmount.add(cartProduct.getPromotionAmount());
        }
        return promotionAmount;
    }

    //    获取活动信息
    private String getPromotionInfo(List<CartProduct> cartProducts) {
        StringBuilder promotionInfo = new StringBuilder();
        for (CartProduct cartProduct : cartProducts) {
            if (cartProduct.getPromotionName() != null) {
                promotionInfo.append(cartProduct.getPromotionName() + ";");
            }
        }
        return promotionInfo.toString();
    }

}
